package com.salton123.camera;

import android.content.Context;
import android.graphics.SurfaceTexture;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.Log;
import android.view.MotionEvent;


import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class VirtualBackgroundRenderer implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener {

    protected static final String TAG = "CameraV1Renderer";
    protected Context mContext;

    protected int mTextureCameraOES = -1;

    protected int cameraWidth = 720;
    protected int cameraHeight = 1280;

    protected SurfaceTexture mSurfaceTexture;
    protected float[] cameraTransformMatrix = new float[16];
    protected float[] screenTransformMatrix = new float[16];
    protected CameraV1 mCamera;
    protected boolean bIsPreviewStarted;

    protected int windowWidth;
    protected int windowHeight;

    protected int frameCount = 0;

    private boolean updateSurface = false;

    public void apply(Context context, CameraV1 camera, boolean isPreviewStarted) {
        mContext = context;
        mCamera = camera;
        bIsPreviewStarted = isPreviewStarted;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

        mTextureCameraOES = GlUtil.createOESTexture();
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        windowWidth = width;
        windowHeight = height;
        computeTrans(cameraWidth, cameraHeight);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        if (mCamera == null) {
            Log.e(TAG, "onDrawFrame: no cam");
            return;
        }

        frameCount++;

        if (mSurfaceTexture != null && updateSurface) {
            mSurfaceTexture.updateTexImage();
            mSurfaceTexture.getTransformMatrix(cameraTransformMatrix);
            updateSurface = false;
        }

        if (!bIsPreviewStarted) {
            bIsPreviewStarted = initSurfaceTexture();
            return;
        }
    }

    protected boolean onTouchEvent(MotionEvent event) {
        return true;
    }

    public boolean initSurfaceTexture() {
        if (mCamera == null) {
            Log.e(TAG, "mCamera is null!");
            return false;
        }
        mSurfaceTexture = new SurfaceTexture(mTextureCameraOES);
        mSurfaceTexture.setOnFrameAvailableListener(this);
        mCamera.setPreviewTexture(mSurfaceTexture);
        mCamera.startPreview();
        return true;
    }

    public void computeTrans(int width, int height) {
        float cameraRatio = (float) width / height;
        float windowRatio = (float) windowWidth / windowHeight;
        Matrix.setIdentityM(screenTransformMatrix, 0);
        if (cameraRatio > windowRatio) {
            float a = 1 - (cameraRatio - windowRatio);
            Matrix.scaleM(screenTransformMatrix, 0, 1f, a, 1f);
        } else if (cameraRatio < windowRatio) {
            float a = 1 - (windowRatio - cameraRatio);
            Matrix.scaleM(screenTransformMatrix, 0, a, 1f, 1f);
        }
    }

    public void deinit() {

        if (mSurfaceTexture != null) {
            mSurfaceTexture.release();
            mSurfaceTexture = null;
        }
        mCamera = null;

        int[] tmp = {mTextureCameraOES};
        GLES20.glDeleteTextures(1, tmp, 0);
        mTextureCameraOES = -1;
        bIsPreviewStarted = false;
    }

    @Override
    public void onFrameAvailable(SurfaceTexture surfaceTexture) {
        updateSurface = true;
    }
}
